package hu.u_szeged.inf.ovrt.filelister.commands;

import static hu.u_szeged.inf.ovrt.filelister.core.beans.Colors.DEFTEXT;
import static hu.u_szeged.inf.ovrt.filelister.core.beans.Colors.DIRECTORY;
import static hu.u_szeged.inf.ovrt.filelister.core.beans.Colors.FILE;
import static hu.u_szeged.inf.ovrt.filelister.core.beans.Colors.INFO;
import hu.u_szeged.inf.ovrt.filelister.core.beans.ApplicationState;
import hu.u_szeged.inf.ovrt.filelister.core.utils.FileIterator;
import hu.u_szeged.inf.ovrt.filelister.core.utils.FileList;
import hu.u_szeged.inf.ovrt.filelister.core.utils.SizeFormatter;
import hu.u_szeged.inf.ovrt.filelister.ui.UserInterface;

import java.awt.Color;
import java.io.File;
import java.text.DateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import java.util.regex.Pattern;

/**
 * Listing module.
 */
public class Ls extends AbstractCommand {

    /**
     * Constructor, that sets user interface.
     * @param ui user interface.
     */
    public Ls(UserInterface ui) {
        super(ui);
    }

    @Override
    public void execute(ApplicationState state, Map<String, String> parameters) {
        if (state.getFile() != null) {
            File[] fileList = state.getFile().listFiles();
            List<File> fileNames = new ArrayList<File>(Arrays.asList(fileList));
            List<String> filters = state.getFilters();
            FileList fileNamesList;
            boolean colorMode = false;
            boolean fileMode = false;
            boolean dirMode = false;
            boolean verboseMode = false;

            fileNamesList = new FileList(fileNames);

            if (parameters.containsKey("c")) {
                colorMode = true;
            } else if (parameters.containsKey("f")) {
                fileMode = true;
            } else if (parameters.containsKey("d")) {
                dirMode = true;
            } else if (parameters.containsKey("l")) {
                verboseMode = true;
            }

            if (filters.size() > 0) {
                getUi().printLn("Applying " + filters.size() + " filter(s)", INFO);

                ListIterator<String> filterIterator = filters.listIterator();
                while (filterIterator.hasNext()) {
                    Pattern pattern = Pattern.compile(filterIterator.next());

                    FileIterator fileIterator = fileNamesList.getFileIterator();

                    while (fileIterator.hasNext()) {
                        if (pattern.matcher(fileIterator.next().getName()).matches()) {
                            fileIterator.remove();
                        }
                    }
                }
            }

            FileIterator printIterator = fileNamesList.getFileIterator();
            while (printIterator.hasNext()) {
                File f = printIterator.next();
                Color col = DEFTEXT;

                if ((fileMode || f.isFile()) && (dirMode || f.isDirectory())) {
                    continue;
                }

                if (colorMode) {
                    if (f.isDirectory()) {
                        col = DIRECTORY;
                    } else {
                        col = FILE;
                    }
                }

                if (verboseMode) {
                    String extra = "";
                    extra += f.isDirectory() ? "d" : "-";
                    extra += f.canRead() ? "r" : "-";
                    extra += f.canWrite() ? "w" : "-";
                    extra += f.canExecute() ? "x " : "- ";
                    extra += DateFormat.getInstance().format(new Date(f.lastModified())) + " ";
                    if (f.isFile()) {
                        extra += String.format("%10s ", SizeFormatter.formatSize(f.length(), 2));
                    } else {
                        extra += "           ";
                    }

                    getUi().print(extra, col);
                }
                getUi().print(f.getName(), col);
                getUi().printLn("", col);

            }
        }
    }
}
